package com.swak.algs.paxos;

import java.util.concurrent.atomic.AtomicInteger;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 * 接受
 * 
 * @author 618lf
 */
public class Acceptor extends IoEvent {

	private static AtomicInteger SN = new AtomicInteger(1);

	private static Logger log = LoggerFactory.getLogger(Acceptor.class);

	/**
	 * 承诺的最小编号，小于此编号的议案直接拒绝
	 */
	int pb;

	/**
	 * 接收的最大的编号的议案的编号
	 */
	int ab;

	/**
	 * 接收的最大的编号的议案的内容
	 */
	Object av;

	/**
	 * 通讯网络
	 */
	NetWork netWork;

	/**
	 * 名称
	 */
	String name;

	public Acceptor(NetWork netWork) {
		this.netWork = netWork;
		this.name = "参议员" + SN.getAndIncrement();
	}

	/**
	 * 收到Prepare阶段的数据
	 */
	public void onPrepare(Proposal proposal) {
		if (proposal.getB() > pb) {
			this.pb = proposal.getB();
			PrepareResult result = new PrepareResult();
			result.setOk(true);
			result.setAb(ab);
			result.setAv(av);
			result.setProposerId(proposal.getProposerId());
			log.debug("参议员 - 准备阶段： {} 编号 {} - {} - {} - {}", name, proposal.getB(), "同意", av,
					proposal.getProposerName());
			this.netWork.sendPrepareResponseMessage(result);
		} else {
			PrepareResult result = new PrepareResult();
			result.setOk(false);
			result.setProposerId(proposal.getProposerId());
			log.debug("参议员 - 准备阶段： {} 编号 {} - {} - {}；原因：编号不能小于 {}", name, proposal.getB(), "拒绝",
					proposal.getProposerName(), this.pb);
			this.netWork.sendPrepareResponseMessage(result);
		}
	}

	/**
	 * 收到Accept阶段的数据
	 */
	public void onAccept(Proposal proposal) {
		if (proposal.b == this.pb) {
			this.ab = proposal.b;
			this.av = proposal.v;
			AcceptResult result = new AcceptResult();
			result.setOk(true);
			result.setProposerId(proposal.getProposerId());
			log.debug("参议员 - 接受阶段：{} 编号 {} - {} - {}", name, proposal.getB(), "同意", this.av);
			this.netWork.sendAcceptResponseMessage(result);
		} else {
			AcceptResult result = new AcceptResult();
			result.setOk(false);
			result.setProposerId(proposal.getProposerId());
			this.netWork.sendAcceptResponseMessage(result);
			log.debug("参议员 - 接受阶段：{} 编号 {} - {}；原因：编号必须等于 {}", name, proposal.getB(), "拒绝", this.pb);
		}
	}
}
